package cn.itcast.hotel.service.impl;

import cn.itcast.hotel.mapper.HotelMapper;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.pojo.result.FilterResult;
import cn.itcast.hotel.pojo.result.PageResult;
import cn.itcast.hotel.pojo.vo.RequestTermParams;
import cn.itcast.hotel.service.IHotelService;
import cn.itcast.hotel.utils.BasicQueryUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 搜索查询(分页条件查询)
     * @param requestParams
     * @return
     */
    public PageResult searchPageInfo(RequestTermParams requestParams) throws IOException {
        SearchRequest request = new SearchRequest("hotel");
        BasicQueryUtil basicQuery = new BasicQueryUtil();

        int page = requestParams.getPage();
        int size = requestParams.getSize();
        SearchRequest request1 = basicQuery.buildBasicQuery(requestParams, request);
        request1.source().from((page - 1)* size / size).size(size);

        SearchResponse response = restHighLevelClient.search(request1, RequestOptions.DEFAULT);

        long total = response.getHits().getTotalHits().value;
        ArrayList<HotelDoc> list = new ArrayList<>();
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {

            String sourceAsString = hit.getSourceAsString();
            HotelDoc hotelDoc = JSONObject.parseObject(sourceAsString, HotelDoc.class);

            list.add(hotelDoc);
        }
        return PageResult.builder()
                .total(total)
                .hotels(list)
                .build();
    }

    @Override
    public FilterResult searchFilter(RequestTermParams requestTermParams) throws IOException {
        SearchRequest request = new SearchRequest("hotel");
//        调用搜索工具类
        BasicQueryUtil basicQueryUtil = new BasicQueryUtil();
        SearchRequest query = basicQueryUtil.buildBasicQuery(requestTermParams, request);

        if (StringUtils.isNotBlank(requestTermParams.getLocation())) {
            request.source().sort(SortBuilders.geoDistanceSort("location", new GeoPoint(requestTermParams.getLocation())).order(SortOrder.ASC).unit(DistanceUnit.KILOMETERS));
        }

        SearchResponse response = restHighLevelClient.search(query, RequestOptions.DEFAULT);
        ArrayList<String> city = new ArrayList<>();
        ArrayList<String> starName = new ArrayList<>();
        ArrayList<String> brand = new ArrayList<>();

        SearchHit[] hits = response.getHits().getHits();
        for (int i = 1; i < response.getHits().getHits().length + 1; i++) {
            Object[] distance = hits[i].getSortValues();


            String string = hits[i - 1].getSourceAsString();
            HotelDoc hotelDoc = JSONObject.parseObject(string, HotelDoc.class);
            if (ArrayUtils.isNotEmpty(distance)) {
                hotelDoc.setDistance(distance[0]);
            }
            if (hotelDoc.getCity() != null && (!hotelDoc.getCity().equals(city.get(i - 1)))) {
                city.add(hotelDoc.getCity());
            }
            if (hotelDoc.getStarName() != null && (!hotelDoc.getStarName().equals(starName.get(i - 1)))) {
                starName.add(hotelDoc.getStarName());
            }
            if (hotelDoc.getBrand() != null && (!hotelDoc.getBrand().equals(brand.get(i - 1)))) {
                brand.add(hotelDoc.getBrand());
            }


        }


        return FilterResult.builder()
                .city(city)
                .starName(starName)
                .brand(brand)
                .build();

    }

    /**
     * 拼音补全搜索
     * @param key
     * @return
     */
    public List<String> searchSpell(String key) throws IOException {
        ArrayList<String> list = new ArrayList<>();
        SearchRequest request = new SearchRequest("hotel");
        request.source().suggest(new SuggestBuilder().addSuggestion("brandAndBusinessSuggestion", SuggestBuilders.completionSuggestion("suggestion").prefix(key).skipDuplicates(true).size(100)));
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        Suggest suggest = response.getSuggest();
        CompletionSuggestion suggestion =  suggest.getSuggestion("brandAndBusinessSuggestion");
        List<CompletionSuggestion.Entry.Option> options = suggestion.getOptions();
        for (CompletionSuggestion.Entry.Option option : options) {
            String text = option.getText().string();
            list.add(text);
        }

        return list;
    }
}
